/**
 * #### 带有过期时间的值的数据结构接口
 */
interface TimeLimitedData<T> {
  /**
   * #### 过期时间
   */
  exceedTime: number;
  /**
   * #### 值
   */
  value: T;
}

/**
 * ### 带有过期时间的值的数据结构的缓存类
 * @author JYeontu
 * @see https://juejin.cn/post/7323205509867143220
 */
class TimeLimitedCache<T> {
  protected map: Map<string, TimeLimitedData<T>>;
  constructor() {
    this.map = new Map<string, TimeLimitedData<T>>();
    // 在构造函数中初始化map
  }

  /**
   * #### 设置缓存数据
   * @param key 键
   * @param value 值
   * @param duration 持续维持的时间，单位为毫秒
   * @returns
   */
  set(key: string, value: T, duration: number) {
    // 定义一个set方法，用于设置缓存数据
    let res = true;
    // 定义一个布尔类型的变量res，用于判断是否设置成功
    if (!this.get(key)) res = false;
    // 如果get方法返回false，则res为false
    const obj: TimeLimitedData<T> = {
      exceedTime: new Date().getTime() + duration,
      value,
    };
    // 定义一个TimeLimitedData类型的变量obj，用于存储缓存数据
    this.map.set(key, obj);
    // 将obj存储到map中
    return res;
    // 返回res
  }

  /**
   * #### 获取缓存数据
   * @param key 键
   * @returns
   */
  get(key: string) {
    // 定义一个get方法，用于获取缓存数据
    const data = this.map.get(key);
    // 从map中获取key对应的值
    if (!data) return false;
    // 如果data为空，则返回false
    const { exceedTime } = data;
    // 从data中获取过期时间
    if (exceedTime <= new Date().getTime()) {
      this.map.delete(key);
      // 如果过期时间小于等于当前时间，则从map中删除key对应的值
      return false;
    }
    // 返回data的值
    return data.value;
  }

  /**
   * #### 获取缓存中没过期的数据数量
   * @returns 缓存数据的数量
   */
  count() {
    // 定义一个count方法，用于获取缓存数据的数量
    let res = 0;
    // 定义一个整数类型的变量res，用于存储缓存数据的数量
    const dateTime = new Date().getTime();
    // 获取当前时间
    this.map.forEach((item) => {
      // 遍历map中的所有值
      const { exceedTime } = item;
      // 从item中获取过期时间
      if (exceedTime > dateTime) res++;
      // 如果过期时间大于当前时间，则res加1
    });
    return res;
    // 返回res
  }
}

export default TimeLimitedCache;
